package com.asb.service;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dingtalktodo_1_0.models.CreateTodoTaskHeaders;
import com.aliyun.dingtalktodo_1_0.models.CreateTodoTaskRequest;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.asb.utils.AccessUtil;
import com.asb.utils.HttpTools;
import com.asb.utils.JsonUtil;
import com.asb.utils.ProcessType;
import com.asb.utils.PropertiesKit;
import com.asb.utils.Strings;
import com.asb.vo.DingTalkTaskVO;
import com.asb.vo.DingTalkTempFileVO;
import com.asb.vo.UsersVO;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.request.OapiProcessInstanceTerminateRequest;
import com.dingtalk.api.request.OapiProcessInstanceTerminateRequest.TerminateProcessInstanceRequestV2;
import com.dingtalk.api.request.OapiProcessinstanceCreateRequest;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
import com.dingtalk.api.response.OapiProcessInstanceTerminateResponse;
import com.dingtalk.api.response.OapiProcessinstanceCreateResponse;
import com.jfinal.aop.Inject;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Record;
import com.taobao.api.ApiException;

import cn.hutool.core.util.RandomUtil;

public class NotifyDingTalkService {

	public static Logger log = Logger.getLogger(NotifyDingTalkService.class);

	@Inject
	UserDingTalkService userService;
	
	/**
	 * 接口
	 **/
	public String notify(String id, String requestBody) throws Exception {
		// 返回信息
		Map<String, String> resultMap = new HashMap<>();
		
		if (Strings.isNullOrEmpty(id) || Strings.isNullOrEmpty(requestBody)) {
			resultMap.put("code", "9001");
			resultMap.put("msg", "传递参数错误，请检查id和body内容是否为空");
			resultMap.put("taskid", "");
			return JSON.toJSONString(resultMap);
		}
		
		log.info("传递接口参数: " + id + " : " + requestBody);

		Map<String, Object> jsonParam = JSON.parseObject(requestBody);

		String process_type = String.valueOf(jsonParam.get("process_type"));

		List<UsersVO> list = (List<UsersVO>) JSONObject.parseArray(String.valueOf(jsonParam.get("users")),
				UsersVO.class);

		// 查询订单
		Map<String, Object> dbMap = this.selectMovetasktableInfo(id);

		if (dbMap == null) {
			resultMap.put("code", "9002");
			resultMap.put("msg", "传递参数id，查询没有找到记录");
			resultMap.put("taskid", "");
			return JSON.toJSONString(resultMap);
		}

		String taskid = "";
		for (UsersVO vo : list) {
			// 获取userid
			String userString = userService.getUserIdByMobile(vo.getPhone_number());
			String userId = String.valueOf(JsonUtil.toRes(userString).get("userid"));
			// 获取来源userid
			String originString = userService.getUserIdByMobile(String.valueOf(dbMap.get("proposerphone")));
			String originId = String.valueOf(JsonUtil.toRes(originString).get("userid"));

			// 发送OA（待审核）
			if (ProcessType.MAIN_AUDIT.equals(process_type)) {
				// 查询钉钉记录
				Map<String, Object> taskMap = this.selectTasktableInfo(id);
				// 撤销处理
				if (taskMap != null) {
					String result = terminateProcess(userId, String.valueOf(taskMap.get("task_id")));
					Map<String, Object> map = JsonUtil.toTask(result);
					String errCode = String.valueOf(map.get("errcode"));
					String status;
					if (!"0".equals(errCode)) {
						status = "2";
					} else {
						status = "1";
					}
					log.info("OA审批撤销: " + result);

					DingTalkTaskVO task = new DingTalkTaskVO();
					task.setId(Integer.parseInt(id));
					task.setTask_id(String.valueOf(taskMap.get("task_id")));
					task.setStatus(status);
					task.setRemark(result);
					this.updateDb(task);
				}
				// 发送处理
				String result = sendProcess(userId, originId, dbMap);
				Map<String, Object> map = JsonUtil.toTask(result);
				String errCode = String.valueOf(map.get("errcode"));
				String status;
				if (!"0".equals(errCode)) {
					status = "3";
				} else {
					status = "0";
					taskid += String.valueOf(map.get("process_instance_id") + ",");
				}
				log.info("OA审批信息: " + result);

				// 记录
				DingTalkTaskVO task = new DingTalkTaskVO();
				task.setId(Integer.parseInt(id));
				task.setTask_id(String.valueOf(map.get("process_instance_id")));
				task.setUser_id(userId);
				task.setMobile(vo.getPhone_number());
				task.setProcess_type(process_type);
				task.setActivity_type(vo.getActivity_type());
				task.setStatus(status);
				task.setFlow_kb("1");
				task.setRemark(result);
				this.saveDb(task);

			}

			// 发送通知（待配合、待执行）
			else if (ProcessType.SUB_WAITING_COOPERATE.equals(vo.getActivity_type())
					|| ProcessType.SUB_WAITING_EXECUTE.equals(vo.getActivity_type())) {
				String result = sendConversation(userId, dbMap);
				Map<String, Object> map = JsonUtil.toTask(result);
				String errCode = String.valueOf(map.get("errcode"));
				String status;
				if (!"0".equals(errCode)) {
					status = "4";
				} else {
					status = "0";
					taskid += String.valueOf(map.get("task_id")) + ",";
				}
				log.info("通知信息: " + result);

				// 记录
				DingTalkTaskVO task = new DingTalkTaskVO();
				task.setId(Integer.parseInt(id));
				task.setTask_id(String.valueOf(map.get("task_id")));
				task.setUser_id(userId);
				task.setMobile(vo.getPhone_number());
				task.setProcess_type(process_type);
				task.setActivity_type(vo.getActivity_type());
				task.setStatus(status);
				task.setFlow_kb("0");
				task.setRemark(result);
				this.saveDb(task);
			}
		}
		resultMap.put("code", "0");
		resultMap.put("msg", "成功");
		resultMap.put("taskid", taskid);

		return JSON.toJSONString(resultMap);
	}

	/**
	 * 根据单号获取信息-DB
	 **/
	public Map<String, Object> selectMovetasktableInfo(String id) {
		List<Map<String, Object>> resList = new ArrayList<>();
		StringBuffer buffer = new StringBuffer();
		buffer.append(
				" SELECT a.ID as id ,a.NO as no, a.ACTIVITYNAME as activityname, a.PROPOSERNAME as proposername ,a.PROPOSERPHONE AS proposerphone ");
		buffer.append(" ,a.STARTCITY as startcity ,a.TROUBLESPECIALTY as troublespecialty ,a.THEME as theme ");
		buffer.append(" ,a.FEEDBACKTIME as feedbacktime ,a.SUMMARY as summary ");
		buffer.append(" from movetasktable a ");
		buffer.append(" WHERE a.ID=? ");
		List<Record> list = Db.find(buffer.toString(), id);

		list.stream().forEach(record -> {
			Map<String, Object> map = record.toMap();
			resList.add(map);
		});

		if (resList.size() <= 0) {
			return null;
		} else {
			return resList.get(0);
		}
	}

	/**
	 * 根据单号获取信息-DB
	 **/
	public boolean saveDb(DingTalkTaskVO vo) {
		boolean resBool = Db.tx(new IAtom() {
			@Override
			public boolean run() throws SQLException {
				Record task = new Record().set("id", vo.getId()).set("task_id", vo.getTask_id())
						.set("user_id", vo.getUser_id()).set("mobile", vo.getMobile())
						.set("process_type", vo.getProcess_type()).set("activity_type", vo.getActivity_type())
						.set("status", vo.getStatus()).set("createtime", new Date()).set("flow_kb", vo.getFlow_kb())
						.set("remark", vo.getRemark());

				// 主表
				boolean bool = Db.save("dingtalk_task", task);

				return bool;
			}
		});

		return resBool;
	}

	/**
	 * 根据单号获取信息-钉钉的task表-DB
	 **/
	public Map<String, Object> selectTasktableInfo(String id) {
		List<Map<String, Object>> resList = new ArrayList<>();
		StringBuffer buffer = new StringBuffer();
		buffer.append(" SELECT id, task_id, user_id, mobile, process_type, activity_type, status, flow_kb ");
		buffer.append(" FROM dingtalk_task ");
		buffer.append(" WHERE ID=? and status='0' and flow_kb='1' ");
		buffer.append(" ORDER BY createtime desc ");
		List<Record> list = Db.find(buffer.toString(), id);

		list.stream().forEach(record -> {
			Map<String, Object> map = record.toMap();
			resList.add(map);
		});

		if (resList.size() <= 0) {
			return null;
		} else {
			return resList.get(0);
		}
	}

	/**
	 * 更新-钉钉的task表-DB
	 **/
	public boolean updateDb(DingTalkTaskVO task) {

		String sql = "update dingtalk_task set status=?, createtime=?, remark=? where id = ? and task_id = ?";
		// 事务处理
		boolean succeed = false;
		try {
			succeed = Db.tx(new IAtom() {
				@Override
				public boolean run() throws SQLException {
					int result = Db.update(sql, task.getStatus(), new Date(), task.getRemark(), task.getId(),
							task.getTask_id());

					return result == 1;
				}
			});
		} catch (Exception e) {
			//e.printStackTrace();
			log.error("",e);
			succeed = false;
		}

		return succeed;
	}

	/**
	 * 通知-钉钉
	 **/
	public String sendConversation(String userid, Map<String, Object> dbMap) throws ApiException {
		DingTalkClient client = new DefaultDingTalkClient(
				"https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");
		OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
		request.setAgentId(PropertiesKit.getAgentid());
		request.setUseridList(userid);
		request.setToAllUser(false);
		OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
		msg.setActionCard(new OapiMessageCorpconversationAsyncsendV2Request.ActionCard());
		msg.getActionCard().setTitle("任务通知");
		String mssage = "#### 任务通知 : \n   ##### 当前活动:" + (dbMap.get("no") == null ? "" : String.valueOf(dbMap.get("no")) + " \n");
		mssage += " ##### 任务主题: " + (dbMap.get("theme") == null ? "" : String.valueOf(dbMap.get("theme")));
		Date t = new Date();
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		msg.getActionCard().setMarkdown(mssage);
		msg.getActionCard().setSingleTitle(df.format(t));
		msg.getActionCard().setSingleUrl("eapp://pages/switchPages/approve");
		msg.setMsgtype("action_card");
		request.setMsg(msg);

		OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, AccessUtil.getAccess_token());
		System.out.println(rsp.getBody());

		return rsp.getBody();
	}

	/**
	 * 待办-钉钉
	 **/
	public void sendTask(String unionid) throws Exception {
		com.aliyun.dingtalktodo_1_0.Client client = AccessUtil.createClient();
		CreateTodoTaskHeaders createTodoTaskHeaders = new CreateTodoTaskHeaders();
		createTodoTaskHeaders.xAcsDingtalkAccessToken = AccessUtil.getAccess_token();
		CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs notifyConfigs = new CreateTodoTaskRequest.CreateTodoTaskRequestNotifyConfigs()
				.setDingNotify("1");
		CreateTodoTaskRequest createTodoTaskRequest = new CreateTodoTaskRequest()
				.setSourceId("isv_dingtalkTodo" + RandomUtil.randomInt()).setSubject("测试待办任务").setCreatorId(unionid)
				.setDescription(
						"应用可以调用该接口发起一个钉钉待办任务，该待办事项会出现在钉钉客户端“待办”页面，需要注意的是，通过开放接口发起的待办，目前仅支持直接跳转ISV应用详情页（ISV在调该接口时需传入自身应用详情页链接）。")
				.setDueTime(System.currentTimeMillis() + 1000 * 60 * 5).setExecutorIds(java.util.Arrays.asList(unionid))
				.setParticipantIds(java.util.Arrays.asList(unionid)).setIsOnlyShowExecutor(true).setPriority(20)
				.setNotifyConfigs(notifyConfigs);
		try {
			client.createTodoTaskWithOptions(unionid, createTodoTaskRequest, createTodoTaskHeaders,
					new RuntimeOptions());
		} catch (TeaException err) {
			err.printStackTrace();
			if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
				// err 中含有 code 和 message 属性，可帮助开发定位问题
			}

		} catch (Exception _err) {
			_err.printStackTrace();
			TeaException err = new TeaException(_err.getMessage(), _err);
			if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
				// err 中含有 code 和 message 属性，可帮助开发定位问题
			}

		}
	}

	/**
	 * OA审批-发送-钉钉
	 **/
	public String sendProcess(String userId, String originatorUserId, Map<String, Object> dbMap) throws ApiException {
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/create");
		OapiProcessinstanceCreateRequest req = new OapiProcessinstanceCreateRequest();
		req.setAgentId(PropertiesKit.getAgentid());
		req.setProcessCode(PropertiesKit.getProcesscode());
		req.setOriginatorUserId(originatorUserId);
		req.setDeptId(-1L);
		req.setApprovers(userId);

		// 单行输入框
		List<OapiProcessinstanceCreateRequest.FormComponentValueVo> formComponentValueVoList = new ArrayList<OapiProcessinstanceCreateRequest.FormComponentValueVo>();
		OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo1 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
		formComponentValueVoList.add(formComponentValueVo1);
		OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo2 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
		formComponentValueVoList.add(formComponentValueVo2);
		OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo3 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
		formComponentValueVoList.add(formComponentValueVo3);
		OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo4 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
		formComponentValueVoList.add(formComponentValueVo4);
		OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo5 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
		formComponentValueVoList.add(formComponentValueVo5);
		OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo6 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
		formComponentValueVoList.add(formComponentValueVo6);
		OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo7 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
		formComponentValueVoList.add(formComponentValueVo7);
		OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo8 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
		formComponentValueVoList.add(formComponentValueVo8);
		OapiProcessinstanceCreateRequest.FormComponentValueVo formComponentValueVo9 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
		formComponentValueVoList.add(formComponentValueVo9);
		formComponentValueVo1.setName("任务编号");
		formComponentValueVo1.setValue(dbMap.get("no") == null ? "" : String.valueOf(dbMap.get("no")));
		formComponentValueVo2.setName("发起地市");
		formComponentValueVo2.setValue(dbMap.get("startcity") == null ? "" : String.valueOf(dbMap.get("startcity")));
		formComponentValueVo3.setName("发起人");
		formComponentValueVo3
				.setValue(dbMap.get("proposername") == null ? "" : String.valueOf(dbMap.get("proposername")));
		formComponentValueVo4.setName("联系电话");
		formComponentValueVo4
				.setValue(dbMap.get("proposerphone") == null ? "" : String.valueOf(dbMap.get("proposerphone")));
		formComponentValueVo5.setName("当前活动");
		formComponentValueVo5
				.setValue(dbMap.get("activityname") == null ? "" : String.valueOf(dbMap.get("activityname")));
		formComponentValueVo6.setName("专业");
		formComponentValueVo6
				.setValue(dbMap.get("troublespecialty") == null ? "" : String.valueOf(dbMap.get("troublespecialty")));
		formComponentValueVo7.setName("任务主题");
		formComponentValueVo7.setValue(dbMap.get("theme") == null ? "" : String.valueOf(dbMap.get("theme")));
		formComponentValueVo8.setName("要求完成时间");
		formComponentValueVo8
				.setValue(dbMap.get("feedbacktime") == null ? "" : String.valueOf(dbMap.get("feedbacktime")));
		formComponentValueVo9.setName("任务摘要");
		formComponentValueVo9.setValue(dbMap.get("summary") == null ? "" : String.valueOf(dbMap.get("summary")));

		req.setFormComponentValues(formComponentValueVoList);
		OapiProcessinstanceCreateResponse rsp = client.execute(req, AccessUtil.getAccess_token());
		System.out.println(JSON.toJSONString(rsp.getBody()));

		return rsp.getBody();
	}

	/**
	 * OA审批-撤销-钉钉
	 **/
	public String terminateProcess(String userId, String taskid) throws ApiException {

		DingTalkClient client = new DefaultDingTalkClient(
				"https://oapi.dingtalk.com/topapi/process/instance/terminate");
		OapiProcessInstanceTerminateRequest req = new OapiProcessInstanceTerminateRequest();
		TerminateProcessInstanceRequestV2 processInstanceRequestV2 = new TerminateProcessInstanceRequestV2();
		processInstanceRequestV2.setProcessInstanceId(taskid);// KNFQK-xEQPapd-vy3tUyaQ04791647949919
		processInstanceRequestV2.setIsSystem(false);
		processInstanceRequestV2.setRemark("说明");
		processInstanceRequestV2.setOperatingUserid(userId);
		req.setRequest(processInstanceRequestV2);
		OapiProcessInstanceTerminateResponse rsp = client.execute(req, AccessUtil.getAccess_token());
		System.out.println(rsp.getBody());

		return rsp.getBody();
	}

	/**
	 * 删除附件
	 **/
	public int deleteFile(String id, String fileName) throws Exception {

		// 查询子表ID
		/*
		 * List<Record> list =
		 * Db.find("select * from app_accessory_file where KEY_=? and uploadusername=?",
		 * id, username); if (list == null || list.size() <= 0) { return -1; }
		 */
		boolean bool = false;

		// 事务处理
		try {
			bool = Db.tx(new IAtom() {
				@Override
				public boolean run() throws SQLException {

					int res = Db.delete("delete from app_accessory_file where id = ? and filename = ?", id, fileName);
					if (res <= 0) {
						return false;
					}
					return true;
				}
			});
		} catch (Exception e) {
			//e.printStackTrace();
			log.error("",e);
			bool = false;
		}

		return bool ? 0 : -2;

	}
	
	/**
	 * 保存临时附件-DB
	 **/
	public boolean saveTempFile(DingTalkTempFileVO vo) {
		boolean resBool = Db.tx(new IAtom() {
			@Override
			public boolean run() throws SQLException {
				Record task = new Record().set("id", vo.getId()).set("file_name", vo.getFile_name())
						.set("temp_name", vo.getTemp_name()).set("path", vo.getPath())
						.set("createtime", new Date());

				// 主表
				boolean bool = Db.save("dingtalk_temp_file", task);

				return bool;
			}
		});

		return resBool;
	}
	
	/**
	 * 删除临时附件
	 **/
	public int deleteFileTemp(String id, String filename) throws Exception {

		boolean bool = false;

		// 事务处理
		try {
			bool = Db.tx(new IAtom() {
				@Override
				public boolean run() throws SQLException {

					int res = Db.delete("delete from dingtalk_temp_file where id = ? and file_name=? ", id, filename);
					if (res <= 0) {
						return false;
					}
					return true;
				}
			});
		} catch (Exception e) {
			//e.printStackTrace();
			log.error("",e);
			bool = false;
		}

		return bool ? 0 : -2;

	}
	
	/**
	 * 获取临时附件表信息-DB
	 **/
	public List<Map<String, Object>> selectFileFromTemp(String tempid) {
		List<Map<String, Object>> resList = new ArrayList<>();
		StringBuffer buffer = new StringBuffer();
		buffer.append(
				" SELECT a.ID as id ,a.file_name as file_name, a.temp_name as temp_name, a.path as path ");
		buffer.append(" from dingtalk_temp_file a ");
		buffer.append(" WHERE a.ID=? ");
		List<Record> list = Db.find(buffer.toString(), tempid);

		list.stream().forEach(record -> {
			Map<String, Object> map = record.toMap();
			resList.add(map);
		});

		return resList;
	}
	
	/**
	 * 临时附件表发送请求
	 **/
	public List<String> sendFiles(String id, String tempid, String username) {
		List<Map<String, Object>> list = this.selectFileFromTemp(tempid);
		List<String> resultList = new ArrayList<>();
		//接口发送 
		for(Map<String, Object> upfile : list) {
			File file = new File(HttpTools.UPLOAD_TEMP_URL + upfile.get("temp_name"));
			String filename = String.valueOf(upfile.get("file_name"));
			resultList.add(filename);
			if (filename != null && !filename.equals("")) {
				postInteface(id, username, file, filename);
			}
		}
		return resultList;
	}
	
	public Map<String, Object> postInteface(String id, String userName, File file, String filename) {

		// keyValues 保存普通参数
		Map<String, Object> keyValues = new HashMap<>();
		keyValues.put("key", id);
		keyValues.put("userName", userName);
		keyValues.put("model", "MoveTaskTable");

		// filePathMap 保存文件类型的参数名和文件路径
		Map<String, File> filePathMap = new HashMap<>();
		filePathMap.put("file", file);

		// headers
		Map<String, Object> headers = new HashMap<>();
		// COOKIE: Name=Value;Name2=Value2
		headers.put("COOKIE",
				"token=OUFFNzQ0OUU5RDc1ODM0Q0M3QUM5NzdENThEN0Q1NkVEMjhGNzJGNEVGRTNCN0JEODM5NzAyNkI0OEE0MDcxNUZCMjdGNUMxMzdGRUE4MTcwRjVDNkJBRTE2ODgzQURDRjNCQjdBMTdCODc0MzA4QzFFRjlBQkM1MTA0N0MzMUU=");

		String responseStr = null;
		try {
			responseStr = HttpTools.postFormData(HttpTools.REQUEST_URL, filePathMap, keyValues, headers, filename);
		} catch (IOException e) {
			log.error(e);
			Map<String, Object> resultMap = new HashMap<>();
			resultMap.put("code", -9);
			resultMap.put("msg", "请求接口系统错误");
			return resultMap;
		}

		System.out.println(responseStr);
		log.info(responseStr);

		if (responseStr == null) {
			Map<String, Object> resultMap = new HashMap<>();
			resultMap.put("code", -1);
			resultMap.put("msg", "返回信息为空");
			return resultMap;
		} else {
			Map<String, Object> result = JSON.parseObject(responseStr);
			String code = String.valueOf(result.get("status"));
			String msg = String.valueOf(result.get("message"));
			result.put("code", Integer.parseInt(code));
			result.put("msg", msg);
			return result;
		}
	}
}
